#ifndef _PENDING_QUEUE_H
#define _PENDING_QUEUE_H

#include "block_storage.h"
#include <linux/spinlock.h>
#include <linux/wait.h>

#define PENDING_READ 0
#define PENDING_WRITE 1

/*typedef struct{
    int request_type[OUTSTANDING_LIMIT]; //PENDING_READ or PENDING_WRITE
    void *requests[OUTSTANDING_LIMIT];
    int index ;
    int count;
    int first_cxid;
    pthread_mutex_t lock;
}pending_queue_t;*/

pending_queue_t* pending_queue_init();

void add_to_tail(pending_queue_t* p_queue, void *request, int nonce, int type, int timeout);

void* remove_first(pending_queue_t* p_queue);

void* get_by_nonce(pending_queue_t* p_queue, int nonce);

void* get_by_index(pending_queue_t *p_queue, int index, int* type);

void check_timeout(block_storage_t *storage);

int is_empty(pending_queue_t* p_queue);

int is_full(pending_queue_t* p_queue);

typedef struct{
    long blockId;
    char *buf;
    int buf_len;
    int xid;
    int nonce;
    int prepare_received[SERVER_COUNT];
    int write_received[SERVER_COUNT];

    void_completion_t completion;
    void *data;
    int write_sent;
    spinlock_t lock;
}pending_write_t;

pending_write_t* alloc_pending_write(long blockId, int xid, int nonce, char *buf, int buf_len,
     void_completion_t completion, void * data);

void dealloc_pending_write(pending_write_t* p_write);

void pending_write_add_prepare_reply(pending_write_t* p_write, int serverId);

int pending_write_data_ready(pending_write_t* p_write);

void pending_write_add_write_reply(pending_write_t* p_write, int serverId);

int pending_write_ready(pending_write_t* p_write);

void pending_write_timeout(block_storage_t* block_storage, pending_write_t* p_write);

typedef struct{
    char *buf;
    int buf_len;
    long blockId;
    int nonce;
    int serverId;
    int node_received[SERVER_COUNT];

    data_completion_t completion;
    void *data;
    spinlock_t lock;
}pending_read_t;

pending_read_t* alloc_pending_read(long blockId, int nonce, data_completion_t completion, void *data);

void dealloc_pending_read(pending_read_t* p_read);

void pending_read_add_reply(pending_read_t* p_read, int serverId);

int pending_read_ready(pending_read_t* p_read);

void pending_read_timeout(block_storage_t* block_storage, pending_read_t* p_read);


    

#endif
